#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "Section.h"
#include "Coff.h"

#define  ALIGN_FLAG_START_POS 19
#define  ALIGN_FLAG_END_POS 33


char * sectionFlagsMsg[] = {
	"", "", "", "", "", "",
	"code", "Init", 
	"Uninit Data", "", 
	"Info", 
	"","", "Data", 
	"Referenced through GP", 
	"", "", "", "", "1", "2", "4", "8","16", "32", "64", "128", "256", "512", "1024", "2048",
	"4096", "8192", "", "", "", "", "", "Exec", "Read", "Write"
};

int characteristics_flags[] = {
	0x00000000, 0x00000001, 0x00000002, 0x00000004, 0x00000008, 0x00000010,
	0x00000020, 0x00000040, 0x00000080, 0x00000100, 0x00000200, 0x00000400,
	0x00000800, 0x00001000, 0x00008000, 0x00020000, 0x00020000, 0x00040000,
	0x00080000, 0x00100000, 0x00200000, 0x00300000, 0x00400000, 0x00500000,
	0x00600000, 0x00700000, 0x00800000, 0x00900000, 0x00A00000, 0x00B00000,
	0x00C00000, 0x00D00000, 0x00E00000, 0x01000000, 0x02000000, 0x04000000,
	0x08000000, 0x10000000, 0x20000000, 0x40000000, 0x80000000
}; 



Section::Section(int n, Coff *c){
	word32 offset = 0;
	word32 cpos   = 0;
	FILE* fp = c->getFile();
	char * tmp;
	word32 aux;

	this->characteristics = "";
	this->number = n;
	this->coff = c;
	this->defSymIterator = NULL;
	this->refSymIterator = NULL;

	offset = sizeof( CoffHeader ) + c->getHeader()->szOptHeader + ( ( n - 1 ) * sizeof(SectionHeader) );	
	cpos = ftell(fp); // backup the current position
	fseek(fp, offset, SEEK_SET);
	fread(&header, sizeof(SectionHeader), 1, fp);
	fseek(fp, cpos, SEEK_SET); // restore the old position, just in case ... 

	//Calc byte align && characteristics
	for( cpos = 0; cpos < sizeof( characteristics_flags ) / sizeof(int); cpos++ ){
		if( ( header.flags & characteristics_flags[cpos]) == characteristics_flags[cpos] ){
			if( cpos >= ALIGN_FLAG_START_POS && cpos <= ALIGN_FLAG_END_POS ){
				byte_align = atoi(sectionFlagsMsg[cpos]);
			}else if( (aux = strlen( sectionFlagsMsg[cpos]) )  > 0 ){
				aux = strlen( this->characteristics ) + aux + 2; // \0 && space. 
				tmp = (char*)malloc( aux );
				sprintf( tmp, "%s %s", this->characteristics, sectionFlagsMsg[cpos] ); 
				free( this->characteristics );
				this->characteristics = tmp;
			}
		}
	}
}

Section::~Section(){
	free(this->characteristics);
}

int Section::getAlign(){
	return byte_align;
}

char* Section::getTxtFlags(){
	return characteristics;
}

SymIterator* Section::DefSymIterator(){
	if( defSymIterator != NULL ){
		delete defSymIterator;
	}

	defSymIterator = new DefinedSymIterator( this->number, this->getName(), this->coff->getSymbols(), this->coff->getHeader()->nSymbols );
	return defSymIterator;
}

SymIterator* Section::RefSymIterator(){
	if( refSymIterator != NULL ){
		delete refSymIterator;
	}

	refSymIterator = new ReferencedSymIterator( this->coff->getFile(), this->header.nRelocations, this->header.posRelocations, this->coff->getSymbols() );

	return refSymIterator;
}


